Some interesting articles on .NET serialization were published in MSDN Magazine:

Run-time Serialization, Part 1 describes basic (de)serialization using the Serializable attribute.
Run-time Serialization, Part 2 describes more advanced (de)serialization by implementing ISerializable.
Run-time Serialization, Part 3 describes serializing non-serializable objects by implementing ISerializationSurrogate.

This last part also describes the bug that the Binary- and SoapFormatter have: They ignore the return value of SetObjectData.
An object is created by these formatters by using the FormatterServices.GetUninitializedObject function.
This function doesn't call constructors, and therefore leaves you with an uninitialized object.
A solution would be to let SetObjectData create a new object and return that one.

public Object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
{
  MyObject MyObject = new MyObject(); //MyObject gets initialized by the constructor

    //Fill the rest
    MyObject.MyField = (MyType)info.GetValue("MyField",typeof(MyType));
    etc...

   //return obj;  No, do not return the object FormatterServices.GetUninitializedObject created for us.
   //instead, return the one we created ourselves:
   return MyObject;
}

Unfortunately, this does not work because of the bug described.
As long as Microsoft hasn't solved this bug, you could create your own Formatter.
As an alternative, a workaround is described in MSDN Magazine:

Binary Serialization of ADO.NET Objects provides a work-around from this bug by using a ghost Serializer.